import time
import re

from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
import logging
import allure

logger = logging.getLogger(__name__)


class BasePage:
    btn_confirm = '//span[@class="am-modal-btn" and text()="确定"]'  # BasePage

    has_count = '/html/body/div[4]/div[3]/div/div[2]/ul/div/span[1]'
    no_count = '/html/body/div[4]/div[3]/div/div[2]/form/div[3]/div'

    def __init__(self, driver):
        self.driver = driver
        self.wait = WebDriverWait(driver, 10)

        logger.info(f"实例化的新页面:{self.__class__}")
        img = self.driver.get_screenshot_as_png()
        allure.attach(img, '进入新页面')

    @allure.step("定位元素")
    def find_element(self, xpath, has_text=False):
        def f(d):
            el = self.driver.find_element(By.XPATH, xpath)
            if has_text is True:
                if el.text != "":
                    return True
                else:
                    return False
            else:
                return True

        self.wait.until(f)

        el = self.driver.find_element(By.XPATH, xpath)
        logger.info(f"定位到的元素:xpath={xpath},el={el.tag_name}({el.text})")
        return el

    @allure.step("获取系统提示")
    def get_msg(self):

        xpath = '//p[@class="prompt-msg"]'
        el = self.find_element(xpath, has_text=True)

        logger.info(f"得到系统的提示:{el.text}")
        img = self.driver.get_screenshot_as_png()
        allure.attach(img, '获取系统提示')

        return el.text

    @allure.step("JS强制点击")
    def click_by_js(self, el_or_xpath):
        if isinstance(el_or_xpath, str):
            el = self.find_element(el_or_xpath)
        else:
            el = el_or_xpath
        logger.info(f"使用JS进行强制点击:{el.tag_name}")
        return self.driver.execute_script("arguments[0].click()", el)  # JS强制点击

    @allure.step("进入到iframe页面")
    def enter_iframe(self, el_or_xpath):
        if isinstance(el_or_xpath, str):
            el = self.find_element(el_or_xpath)
        else:
            el = el_or_xpath
        logger.info("进入嵌套页面")
        self.driver.switch_to.frame(el)  # 进入嵌套页面

    @allure.step("点击确定")
    def confirm(self):
        self.find_element(self.btn_confirm).click()
        logger.info("点击确定")
        return self.get_msg()

    @allure.step("获取数据的数量")
    def get_data_count(self):
        data_count = None
        try:
            el = self.find_element(self.no_count)
            if " 没有相关数据" in el:
                data_count = 0

        except:
            el = self.find_element(self.has_count)
            p = "共 (.*?) 条数据"
            res = re.findall(p, el.text)[0]
            data_count = int(res)

        logger.info(f"获取数据的数量:{data_count}")
        return data_count


class UserLoginPage(BasePage):
    inpt_username = "/html/body/div[4]/div/div[2]/div[2]/div/div/div[1]/form/div[1]/input"
    inpt_password = "/html/body/div[4]/div/div[2]/div[2]/div/div/div[1]/form/div[2]/div/input"
    btn_submit = "/html/body/div[4]/div/div[2]/div[2]/div/div/div[1]/form/div[3]/button"

    def login(self, username, password):
        self.driver.get("http://116.62.63.211/shop/useraddress/index.html")
        self.find_element(self.inpt_username).send_keys(username)
        self.find_element(self.inpt_password).send_keys(password)
        self.find_element(self.btn_submit).click()
        logger.info(f"使用账号:{username}进行登录")

        return self.get_msg()


class UserAddressPage(BasePage):
    btn_new_address = "/html/body/div[4]/div[3]/div/div/button"
    iframe_new_address = '//iframe[@src="http://116.62.63.211/shop/useraddress/saveinfo.html"]'

    ipt_alias = "/html/body/div[1]/form/div[1]/input"
    ipt_name = "/html/body/div[1]/form/div[2]/input"
    ipt_tel = "/html/body/div[1]/form/div[3]/input"

    sel_province = "/html/body/div[1]/form/div[4]/div[1]/a/span"
    sel_city = "/html/body/div[1]/form/div[4]/div[2]/a/span"
    sel_county = "/html/body/div[1]/form/div[4]/div[3]/a/span"

    ipt_address = '//*[@id="form-address"]'
    btn_submit = "/html/body/div[1]/form/div[7]/button"

    def set_province(self, province):
        self.find_element(self.sel_province).click()
        xpath = f'/html/body/div[1]/form/div[4]/div[1]/div/ul/li[text()="{province}"]'
        self.find_element(xpath).click()
        return True

    def set_city(self, city):
        self.find_element(self.sel_city).click()
        xpath = f'/html/body/div[1]/form/div[4]/div[2]/div/ul/li[text()="{city}"]'
        self.find_element(xpath).click()
        return True

    def set_county(self, county):
        self.find_element(self.sel_county).click()
        xpath = f'/html/body/div[1]/form/div[4]/div[3]/div/ul/li[text()="{county}"]'
        self.find_element(xpath).click()
        return True

    def new_address(self, name, tel, province, city, county, address, alias=""):
        logger.info(f"创建新的收货地址:{(name, tel, province, city, county, address, alias)}")
        self.driver.get("http://116.62.63.211/shop/useraddress/index.html")
        self.find_element(self.btn_new_address).click()
        self.enter_iframe(self.iframe_new_address)
        self.find_element(self.ipt_alias).send_keys(alias)
        self.find_element(self.ipt_name).send_keys(name)
        self.find_element(self.ipt_tel).send_keys(tel)

        self.set_province(province)
        self.set_city(city)
        self.set_county(county)

        self.find_element(self.ipt_address).send_keys(address)
        self.find_element(self.btn_submit).click()

        return self.get_msg()


class UserPersonalPage(BasePage):
    img_avatar = "/html/body/div[4]/div[3]/div/dl/dd[1]/img"
    a_avatar_change = '/html/body/div[4]/div[3]/div/dl/dd[1]/span/a'
    ipt_avatar = '//*[@id="user-avatar-popup"]/div/div[2]/form/div[2]/div/input'
    btn_avatar_submit = '//*[@id="user-avatar-popup"]/div/div[2]/form/button'
    img_xpath = '/html/body/div[4]/div[3]/div/dl/dd[1]/img'

    a_info_change = '/html/body/div[4]/div[3]/div/legend/a'
    ipt_name = '/html/body/div[4]/div[3]/div/form/div[1]/input'
    ipt_birthday = '/html/body/div[4]/div[3]/div/form/div[3]/input'
    btn_info_submit = '/html/body/div[4]/div[3]/div/form/div[4]/button'
    new_name = '/html/body/div[4]/div[3]/div/dl/dd[2]'
    new_sex = '/html/body/div[4]/div[3]/div/dl/dd[3]'
    new_birthday = '/html/body/div[4]/div[3]/div/dl/dd[4]'

    def upload_avatar(self, path):
        self.driver.get("http://116.62.63.211/shop/personal/index.html")
        self.find_element(self.a_avatar_change).click()
        self.find_element(self.ipt_avatar).send_keys(path)
        time.sleep(1)
        self.find_element(self.btn_avatar_submit).click()
        return self.get_msg()

    def get_avatar_url(self):
        self.driver.get("http://116.62.63.211/shop/personal/index.html")
        el = self.find_element(self.img_xpath)
        src = el.get_attribute("src")
        return src

    def set_sex(self, sex):
        xpath = f'/html/body/div[4]/div[3]/div/form/div[2]/div/label[text()=" {sex}			"]'
        self.click_by_js(xpath)

    def info_name(self, name, sex, birthday):
        logger.info(f"设置用户信息:{name, sex, birthday}")
        self.driver.get("http://116.62.63.211/shop/personal/index.html")
        self.find_element(self.a_info_change).click()
        self.find_element(self.ipt_name).clear()
        time.sleep(4)
        self.find_element(self.ipt_name).send_keys(name)
        self.set_sex(sex)
        self.find_element(self.ipt_birthday).clear()
        self.find_element(self.ipt_birthday).send_keys(birthday)
        self.find_element(self.btn_info_submit).click()

        return self.get_msg()

    def assert_info(self):
        self.driver.get("http://116.62.63.211/shop/personal/index.html")
        name = self.find_element(self.new_name, has_text=True)
        sex = self.find_element(self.new_sex, has_text=True)
        birthday = self.find_element(self.new_birthday, has_text=True)
        logger.info(f"获取用户信息:{name.text, sex.text, birthday.text}")
        return name.text, sex.text, birthday.text


class GoodsPage(BasePage):
    p_name = '/html/body/div[4]/div[2]/div[2]/div/div[1]/h1'
    p_price = '/html/body/div[4]/div[2]/div[2]/div/div[2]/div/div[1]/dd/b'
    btn_buy = '/html/body/div[4]/div[2]/div[2]/div/div[3]/div[2]/button[1]'

    @allure.step("立即购买")
    def buy(self):
        self.find_element(self.btn_buy).click()
        # 跳转到下一个页面，因此返回下一个POM
        return BuyPage(self.driver)  # 实例化这个POM

    @allure.step("获取商品名称")
    def get_name(self):
        name = self.find_element(self.p_name, has_text=True).text
        logger.info(f"获取商品名称:{name}")
        return name

    @allure.step("获取商品价格")
    def get_price(self):
        price = float(self.find_element(self.p_price, has_text=True).text)
        logger.info(f"获取商品价格:{price}")
        return price


class BuyPage(BasePage):
    btn_pay_type = '/html/body/div[4]/div/div[4]/ul/li[1]'
    btn_pay_submit = '/html/body/div[4]/div/div[6]/div/form/div/button'

    @allure.step("提交订单")
    def submit(self):
        self.find_element(self.btn_pay_type).click()
        time.sleep(1)
        self.find_element(self.btn_pay_submit).click()
        return self.get_msg()


class OrderPage(BasePage):
    # 删除掉一直在变化的元素,再重新复制xpath即可定位成功
    order_name = '/html/body/div[4]/div[3]/div/div[2]/form/div[3]/table/tbody/tr[1]/td[1]/div[1]/div/a'
    order_count_and_price = '/html/body/div[4]/div[3]/div/div[2]/form/div[3]/table/tbody/tr[1]/td[1]/div[3]'
    order_status = '/html/body/div[4]/div[3]/div/div[2]/form/div[3]/table/tbody/tr[1]/td[2]'
    btn_cancel = '/html/body/div[4]/div[3]/div/div[2]/form/div[3]/table/tbody/tr[1]/td[30]/button'

    @allure.step("订单状态")
    def get_order_status(self):
        status = self.find_element(self.order_status).text
        logger.info(f"获取订单的状态:{status}")
        return status

    @allure.step("获取订单名称")
    def get_order_name(self):
        name = self.find_element(self.order_name).text
        logger.info(f"获取订单的名称:{name}")
        return name

    @allure.step("获取订单中商品的数量")
    def goods_count(self):
        text = self.find_element(self.order_count_and_price).text
        p = "共(.*?)件 合计:￥(.*?)元"
        res = re.findall(p, text)[0]
        count = int(res[0])
        logger.info(f"获取订单中商品的数量:{count}")
        return count

    @allure.step("获取订单价格")
    def order_price(self):
        self.driver.get('http://116.62.63.211/shop/order/index.html')
        text = self.find_element(self.order_count_and_price).text
        p = "共(.*?)件 合计:￥(.*?)元"
        res = re.findall(p, text)[0]
        price = float(res[1])
        logger.info(f"获取订单的价钱:{price}")
        return price

    @allure.step("取消/删除操作")
    def cancel(self, action_type):
        self.driver.get('http://116.62.63.211/shop/order/index.html')
        el = self.find_element(self.btn_cancel)
        assert el.text == action_type  # 验证操作类型
        el.click()
        logger.info(f"点击操作{action_type}")
        return self.confirm()
